
package uk.addie.mp3fixer.visitors;

import java.awt.event.ActionEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.logging.Level;

import javax.swing.AbstractAction;
import javax.swing.Action;

import uk.addie.mp3fixer.MP3Fixer;
import uk.addie.mp3fixer.MP3Handle;

abstract class AbstractVisitor extends SimpleFileVisitor<Path> implements Runnable, Action {
    class Abstraction extends AbstractAction {
        private static final long serialVersionUID = 1L;

        @Override public void actionPerformed(final ActionEvent e) {
            throw new UnsupportedOperationException("Not supported");
        }
    }

    protected Abstraction abstraction = this.new Abstraction();

    @Override public void actionPerformed(final ActionEvent e) {
        final Thread t = new Thread(this, "Visitor runner");
        t.start();
    }

    @Override public void addPropertyChangeListener(final PropertyChangeListener listener) {
        abstraction.addPropertyChangeListener(listener);
    }

    abstract protected String buttonName();

    @Override public Object getValue(final String key) {
        if (Action.NAME.equals(key)) {
            return buttonName();
        }
        return abstraction.getValue(key);
    }

    @Override public boolean isEnabled() {
        return abstraction.isEnabled();
    }

    abstract protected void modifyMp3(final MP3Handle mp3, final Path path);

    @Override public void putValue(final String key, final Object value) {
        abstraction.putValue(key, value);
    }

    @Override public void removePropertyChangeListener(final PropertyChangeListener listener) {
        abstraction.removePropertyChangeListener(listener);
    }

    @SuppressWarnings("static-method") protected Path rootDirectory() {
        return MP3Fixer.getScope();
    }

    @Override public void run() {
        setEnabled(false);
        try {
            Files.walkFileTree(rootDirectory(), this);
        } catch (IOException e1) {
            MP3Fixer.LOG.log(Level.SEVERE, "AbstractVisitor error", e1);
        }
        setEnabled(true);
        MP3Fixer.fileSelector().refresh();
    }

    @Override public void setEnabled(final boolean b) {
        abstraction.setEnabled(b);
    }

    @Override public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
        final MP3Handle mp3 = MP3Handle.withPath(file);
        if (mp3 != null) {
            modifyMp3(mp3, file);
            return FileVisitResult.CONTINUE;
        }
        return FileVisitResult.CONTINUE;
    }
}
